﻿using log4net;
using log4net.Config;
using log4net.Repository;
using Newtonsoft.Json;
using System;
using System.IO;

namespace suirui.ZhuMu.Log
{
    public class Log4netLoger : ILog
    {
        const string RepositoryName = "NETCoreRepository";
        private static ILoggerRepository repository = null;
        private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };

        private log4net.ILog Loger;

        private static ILoggerRepository Repository
        {
            get
            {
                if (repository == null)
                {
                    repository = LogManager.CreateRepository(RepositoryName);
                }
                return repository;
            }
        }

        static Log4netLoger() { }

        internal static void Init(string configPath)
        {
            repository = LogManager.CreateRepository(RepositoryName);
            XmlConfigurator.Configure(Repository, new FileInfo(configPath));
        }

        public Log4netLoger(string loggerName)
        {
            if (string.IsNullOrEmpty(loggerName))
                throw new ArgumentNullException("loggerName");
            Loger = log4net.LogManager.Exists(Repository.Name, loggerName);

            if (Loger == null)
            {
                Loger = CreateLogger(loggerName);
            }
        }

        private log4net.ILog CreateLogger(string loggerName, string savePath = null, string datePattern = "yyyyMM//yyyyMMdd.'log'", string conversionPattern = "%date %-5level %message% %n")
        {

            var logger = log4net.LogManager.Exists(Repository.Name, loggerName);

            if (logger == null)
            {
                var appender = new log4net.Appender.RollingFileAppender
                {
                    Name = "Appender_" + loggerName,
                    AppendToFile = true,
                    MaxSizeRollBackups = 10,
                    StaticLogFileName = false,
                    DatePattern = datePattern,
                    RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Date,
                    Layout = new log4net.Layout.PatternLayout(conversionPattern)
                };
                if (string.IsNullOrEmpty(savePath))
                    appender.File = $"log//{loggerName}//";
                else
                    appender.File = savePath;

                appender.ActivateOptions();

                //var repository = LogManager.CreateRepository(loggerName);
                log4net.Config.BasicConfigurator.Configure(Repository, appender);

                logger = log4net.LogManager.GetLogger(Repository.Name, loggerName);
            }
            return logger;
        }


        #region 一般信息
        /// <summary>
        /// 一般日志
        /// </summary>
        /// <param name="message"></param>
        public void Info(object message)
        {
            Info(message, null);
        }

        /// <summary>
        /// 一般日志
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Info(object message, Exception exception)
        {
            Log(LogLevel.Info, message, exception);
        }
        #endregion

        #region 调试信息

        /// <summary>
        /// 调试日志
        /// </summary>
        /// <param name="message"></param>
        public void Debug(object message)
        {
            Debug(message, null);
        }

        /// <summary>
        /// 调试日志
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Debug(object message, Exception exception)
        {
            Log(LogLevel.Debug, message, exception);
        }

        #endregion

        #region 警告

        /// <summary>
        /// 警告日志
        /// </summary>
        /// <param name="message"></param>
        public void Warn(object message)
        {
            Warn(message, null);
        }
        /// <summary>
        /// 警告日志
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Warn(object message, Exception exception)
        {
            Log(LogLevel.Warn, message, exception);
        }

        #endregion

        #region 一般错误
        /// <summary>
        /// 一般错误
        /// </summary>
        /// <param name="message"></param>
        public void Error(object message)
        {
            Error(message, null);
        }

        /// <summary>
        /// 一般错误
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Error(object message, Exception exception)
        {
            Log(LogLevel.Error, message, exception);
        }

        #endregion

        #region 致命错误

        /// <summary>
        /// 致命错误
        /// </summary>
        /// <param name="message"></param>
        public void Fatal(object message)
        {
            Fatal(message, null);
        }

        /// <summary>
        /// 致命错误
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Fatal(object message, Exception exception)
        {
            Log(LogLevel.Fatal, message, exception);
        }
        #endregion


        public void DebugFormat(string format, params object[] args)
        {
            LogFormat(LogLevel.Debug, format, args);
        }

        public void ErrorFormat(string format, params object[] args)
        {
            LogFormat(LogLevel.Error, format, args);
        }

        public void FatalFormat(string format, params object[] args)
        {
            LogFormat(LogLevel.Fatal, format, args);
        }

        public void InfoFormat(string format, params object[] args)
        {
            LogFormat(LogLevel.Info, format, args);
        }

        public void WarnFormat(string format, params object[] args)
        {
            LogFormat(LogLevel.Warn, format, args);
        }

        /// <summary>
        /// 日志
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <param name="message">日志内容</param>
        /// <param name="exception">异常信息</param>
        public void Log(LogLevel level, object message, Exception exception)
        {
            var msg = JsonConvert.SerializeObject(message, serializerSettings);
            if (msg.Contains("swagger")) return;
            switch (level)
            {
                case LogLevel.Info:
                    Loger.Info(msg, exception);
                    break;
                case LogLevel.Debug:
                    Loger.Debug(msg, exception);
                    break;
                case LogLevel.Warn:
                    Loger.Warn(msg, exception);
                    break;
                case LogLevel.Error:
                    Loger.Error(msg, exception);
                    break;
                case LogLevel.Fatal:
                    Loger.Fatal(msg, exception);
                    break;
                default:
                    break;
            }
        }

        public void LogFormat(LogLevel level, string format, params object[] args)
        {

            switch (level)
            {
                case LogLevel.Info:
                    Loger.InfoFormat(format, args);
                    break;
                case LogLevel.Debug:
                    Loger.DebugFormat(format, args);
                    break;
                case LogLevel.Warn:
                    Loger.WarnFormat(format, args);
                    break;
                case LogLevel.Error:
                    Loger.ErrorFormat(format, args);
                    break;
                case LogLevel.Fatal:
                    Loger.FatalFormat(format, args);
                    break;
                default:
                    break;
            }
        }

    }

    /// <summary>
    /// 日志级别
    /// </summary>
    public enum LogLevel
    {
        /// <summary>
        /// 一般信息
        /// </summary>
        Info,

        /// <summary>
        /// 调试信息
        /// </summary>
        Debug,

        /// <summary>
        /// 警告
        /// </summary>
        Warn,

        /// <summary>
        /// 一般错误
        /// </summary>
        Error,

        /// <summary>
        /// 致命错误
        /// </summary>
        Fatal
    }
}
